package calculator;

import java.util.ArrayList;
import java.util.Collection;
import java.util.Iterator;
import java.util.List;

public class Calculator {

    public int add(String text) {
        if(text.equals("")) {
            return 0;
        } else {
            int[] numbers = extractNumbers(text);
            raiseExceptionIfAnyNegativeNumber(numbers);
            return sum(numbers);
        }
    }

    private static void raiseExceptionIfAnyNegativeNumber(int[] numbers) {
        List<Integer> negatives = negativesOf(numbers);
        if(negatives.size()>0) {
            throw new RuntimeException(
                        String.format("Negative not allowed (%s)",join(negatives,",")));
        }
    }

    private static List<Integer> negativesOf(int[] numbers) {
        List<Integer> negatives = new ArrayList<Integer>();
        for(int number: numbers) {
            if(number < 0) {
                negatives.add(number);
            }
        }
        return negatives;
    }

     private static String join(Collection<?> s, String delimiter) {
         StringBuilder builder = new StringBuilder();
         Iterator iter = s.iterator();
         while (iter.hasNext()) {
             builder.append(iter.next());
             if (!iter.hasNext()) {
               break;
             }
             builder.append(delimiter);
         }
         return builder.toString();
     }


    private int[] extractNumbers(String text) throws NumberFormatException {
        return toIntArray(new Tokenizer(text).tokens());
    }

    private int[] toIntArray(String[] numbersAsString)
            throws NumberFormatException
    {
        int[] numbers = new int[numbersAsString.length];
        for(int i=0; i < numbers.length; i++) {
            numbers[i] = toInt(numbersAsString[i]);
        }
        return numbers;
    }

    private int sum(int[] numbers) {
        int sum = 0;
        for(int number: numbers) {
            sum+=number;
        }
        return sum;
    }

    private static int toInt(String text) {
        return Integer.parseInt(text);
    }

}
